#include "../Inc/LinkList.h"
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>

status LinkList_Init(link_list_t *list) {
    list = (link_list_t *)malloc(sizeof(link_list_t));
    list->next = NULL;

    printf("Link list is allocated storage space successfully\n");
    return OK;
}

status LinkList_Deinit(link_list_t *list) {
    list->next = NULL;
    free(list);
    list = NULL;

    printf("Link list is deinited successfully\n");
    return OK;
}

status LinkList_GetElement(link_list_t *list, unsigned int index, user_link_list_element_t *element) {
    link_list_t *p = list->next;
    size_t j = 0;
    while (p && j < index) {
        p = p->next;
        j++;
    }

    if (!p || j > index) {
        printf("Illegal index value, the %d has not found in this link list.\n", list->data.value);
        return FAIL;
    }

    *element = p->data;

    printf("Find %d in the link list.\n", element->value);
    return OK;
}

link_list_t *LinkList_LocateElement(link_list_t *list, user_link_list_element_t element) {
    link_list_t *p = list->next;
    while(p && p->data.value != element.value) {
        p = p->next;
    }

    if (p == NULL) {
        printf("Fail to locate this element. Please check it.\n");
    }
    else {
        printf("Locate the element %d successfully.\n", p->data.value);
    }

    return p;
}

status LinkList_Insert(link_list_t *list, unsigned int index, user_link_list_element_t element) {
    link_list_t *p = list;

    size_t j = 0;
    while (p && (j < index)) {
        p = p->next;
        j++;
    }

    if (!p || (j > index)) {
        printf("Illegal index value, the %d has not found in this link list.\n", list->data.value);
        return FAIL;
    }

    link_list_t *new_node = (link_list_t *)malloc(sizeof(link_list_t));
    new_node->data = element;
    new_node->next = p->next;
    p->next = new_node;

    printf("Insert new node %d at index %d.\n", element.value, index);
    return OK;
}

status LinkList_Delete(link_list_t *list, unsigned int index) {
    link_list_t *p = list;
    size_t j = 0;
    while(p && (j < index)) {
        p = p->next;
        j++;
    }

    if (!p || (j > index)) {
        printf("Illegal index value, the %d has not found in this link list.\n", list->data.value);
        return FAIL;
    }

    link_list_t *q = p->next;
    p->next = q->next;
    free(q);
    q = NULL;

    printf("Delete node at index %d.\n", index);
    return OK;
}

void LinkList_Create2Front(link_list_t *list, unsigned int number) {
    list = (link_list_t *)malloc(sizeof(link_list_t));
    list->next = NULL;

    for (size_t i = 0; i < number; i++) {
        link_list_t *new_node = (link_list_t *)malloc(sizeof(link_list_t));
        if (!new_node) {
            printf("Fail to allocate storage space.\n");
            return ;
        }

        printf("Insert index %d value in reverse: ", number-i);
        scanf("%d", &new_node->data.value);
        new_node->next = list->next;
        list->next = new_node;
    }

    printf("Create link list successfully, the length is %d", number);
}

// FIXME: *list output is NULL
void LinkList_Create2Back(link_list_t *list, unsigned int number) {
    list = (link_list_t *)malloc(sizeof(link_list_t));
    if (!list) {
        printf("Fail to allocate storage space.\n");
        return ;
    }
    list->next = NULL;

    LinkList_Init(list);

    link_list_t *p = list;

    for (size_t i = 0; i < number; i++) {
        link_list_t *new_node = (link_list_t *)malloc(sizeof(link_list_t));
        if (!new_node) {
            printf("Fail to allocate storage space.\n");
            return ;
        }
        printf("Insert index %d value: ", i);
        scanf("%d", &new_node->data.value);
        new_node->next = NULL;
        p->next = new_node;
        p = p->next;
    }

    printf("Create link list successfully, the length is %d", number);
}

void LinkList_Test(void) {
    link_list_t *list_head = (link_list_t *)malloc(sizeof(link_list_t));

    link_list_t *node_1 = (link_list_t *)malloc(sizeof(link_list_t));
    list_head->next = node_1;
    node_1->data.value = 5;
    node_1->next = NULL;

    link_list_t *node_2 = (link_list_t *)malloc(sizeof(link_list_t));
    node_1->next = node_2;
    node_2->data.value = 50;
    node_2->next = NULL;
    
    // LinkList_Create2Back(list_head, 4);

    user_link_list_element_t *element = (user_link_list_element_t *)malloc(sizeof(user_link_list_element_t));
    element->value = 20;

    LinkList_Insert(list_head, 1, *element);

    LinkList_GetElement(list_head, 0, element);
    LinkList_GetElement(list_head, 1, element);
    LinkList_GetElement(list_head, 2, element);

    LinkList_Delete(list_head, 1);

    LinkList_GetElement(list_head, 0, element);
    LinkList_GetElement(list_head, 1, element);
    LinkList_GetElement(list_head, 2, element);

    free(element);
    element = NULL;
    free(node_2);
    node_2 = NULL;
    free(node_1);
    node_1 = NULL;
    free(list_head);
    list_head = NULL;
}
